package com.suke.money.Web;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.money.suke.utils.Constants;
import com.money.suke.utils.Result;
import com.suke.money.model.User;
import com.suke.money.service.RedisService;
import com.suke.money.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Author: liush
 * @CreateTime: 2022-11-24  16:16
 * @Description: 用户控制层
 */
@Slf4j
@Controller
public class UserController {

    @Reference(interfaceClass = UserService.class, version = "1.0.0", timeout = 20000)
    UserService userService;

    @Reference(interfaceClass = RedisService.class, version = "1.0.0", timeout = 20000)
    RedisService redisService;

    //跳转 注册页面
    @GetMapping("/loan/page/register")
    public String register() {
        return "register.html";
    }

    //审核手机号
    @GetMapping("/loan/page/checkPhone")
    @ResponseBody
    public Object checkPhone(@RequestParam(name = "phone", required = true) String phone) {
        //根据手机号码，查询用户数量，如果=1：说明已注册，否则可以使用
        Integer num = userService.queryUserCountByPhone(phone);
        if (num >= 1) {
            return Result.error("该手机号码已被注册");
        }
        //{"code":1,"message":"","success":true}
        return Result.success();
    }

    //注册提交
    @PostMapping("/loan/page/registerSubmit")
    @ResponseBody
    public Object registerSubmit(@RequestParam(name = "phone", required = true) String phone,
                                 @RequestParam(name = "loginPassword", required = true) String loginPassword,
                                 @RequestParam(name = "messageCode", required = true) String messageCode,
                                 HttpServletRequest request) {
        //校验：短信验证码
        String code = redisService.pop(phone);
        if (!StringUtils.equals(code, messageCode)) {
            return Result.error("验证码错误");
        }
        //注册新用户：1.用户表插入一条记录 2.注册添加888
        User user = userService.register(phone, loginPassword);
        if (!ObjectUtils.allNotNull(user)) { //lang3工具包：ObjectUtils.allNotNull()不会出现空指针异常
            return Result.error("注册失败");
        }
        //缓存登录身份
        request.getSession().setAttribute(Constants.LOGIN_USER, user);
        return Result.success();
    }

    //验证 短信验证码
    @GetMapping("/loan/page/messageCode")
    @ResponseBody
    public Object messageCode(@RequestParam(name = "phone", required = true) String phone,
                              HttpServletRequest request) {
        //此处短信参考：度娘-京东云-京东万象-106短信(京东账号登录免费试用：https://wx.jdcloud.com/market/datas/5/10306)
        //发短信:Url:https://way.jd.com/kaixintong/kaixintong?mobile=18012736372&content=【凯信通】您的验证码是：7758521&appkey=4790ba541724d3ff9e78552a18952ff9

        //生成6位随机数
        String code = Result.generateCode(6);
        Map<String, Object> parasMap = new HashMap<>();
        parasMap.put("mobile", phone);
        parasMap.put("appkey", "4790ba541724d3ff9e78552a18952ff9");
        parasMap.put("content", "【凯信通】您的验证码是：" + code);

        //模拟报文
        //接口只有免费使用10次，后面code1==10010：接口需要付费，请充值，所以只能用此成功的假消息
        String result = "{\n" +
                "    \"code\": \"10000\",\n" +
                "    \"charge\": false,\n" +
                "    \"remain\": 0,\n" +
                "    \"msg\": \"查询成功\",\n" +
                "    \"result\": \"<?xml version=\\\"1.0\\\" encoding=\\\"utf-8\\\" ?><returnsms>\\n <returnstatus>Success</returnstatus>\\n <message>ok</message>\\n <remainpoint>-8609554</remainpoint>\\n <taskID>233651751</taskID>\\n <successCounts>1</successCounts></returnsms>\",\n" +
                "    \"requestId\": \"393d1a4a33814eb6a8df3f6518f568bf\"\n" +
                "}";
        try {
            //result = HttpClientUtils.doPost("https://way.jd.com/kaixintong/kaixintong", parasMap);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("系统异常");
        }
        //code解析 验证通信是否异常
        JSONObject jsonObject = JSONObject.parseObject(result);
        String code1 = jsonObject.getString("code");
        if (!StringUtils.equals(code1, "10000")) {
            //接口只有免费使用10次，后面code1==10010：接口需要付费，请充值，所以只能用上面成功的假消息
            return Result.error("通信异常：" + code1);
        }
        //result——xml解析 验证短信是否发送成功
        String xml = jsonObject.getString("result");
        Document document = null;
        try {
            document = DocumentHelper.parseText(xml);
        } catch (DocumentException e) {
            e.printStackTrace();
            return Result.error("系统升级");
        }
        Node node = document.selectSingleNode("//returnstatus"); //采用XPath语法解析
        String text = node.getText();
        if (!StringUtils.equals(text, "Success")) {
            return Result.error("短息发送失败");
        }
        //redis缓存验证码，不使用session(cookie访问机制)缓存原因：20分钟有效时间太长了，短信验证码几分钟有效即可
        redisService.push(phone, code);
        return Result.success(code);
    }

    //跳转 实名认证页面
    @GetMapping("/loan/page/realName")
    public String realName() {
        return "realName.html";
    }

    //提交更新 实名认证信息
    @PostMapping("/loan/page/realNameSubmit")
    @ResponseBody
    public Object realNameSubmit(@RequestParam(name = "phone", required = true) String phone,
                                 @RequestParam(name = "realName", required = true) String realName,
                                 @RequestParam(name = "idCard", required = true) String idCard,
                                 @RequestParam(name = "messageCode", required = true) String messageCode,
                                 HttpServletRequest request) {
        //校验：短信验证码
        String code = redisService.pop(phone);
        if (!StringUtils.equals(code, messageCode)) {
            return Result.error("验证码错误");
        }
        //验证：是否登录
        User user = (User) request.getSession().getAttribute(Constants.LOGIN_USER);
        if (!ObjectUtils.allNotNull(user)) {
            return Result.error("请登录后，再实名认证");
        }
        //验证：实名认证手机号 是否与 注册或登录用户的手机号 保持一致
        if (!StringUtils.equals(phone, user.getPhone())) {
            return Result.error("请手机号保持一致！");
        }
        //请求参数
        Map<String, Object> parasMap = new HashMap<>();
        parasMap.put("cardNo", idCard);
        parasMap.put("appkey", "4790ba541724d3ff9e78552a18952ff9");
        parasMap.put("realName", realName);
        //模拟报文
        //接口只有免费使用10次，后面code1==10010：接口需要付费，请充值，所以只能用此成功的假消息
        String result = "{\n" +
                "    \"code\": \"10000\",\n" +
                "    \"charge\": false,\n" +
                "    \"remain\": 1305,\n" +
                "    \"msg\": \"查询成功\",\n" +
                "    \"result\": {\n" +
                "        \"error_code\": 0,\n" +
                "        \"reason\": \"成功\",\n" +
                "        \"result\": {\n" +
                "            \"realname\": \"古天乐\",\n" +
                "            \"idcard\": \"350721197702134399\",\n" +
                "            \"isok\": true\n" +
                "        }\n" +
                "    }\n" +
                "}";
        //实名认证
        try {
            //result = HttpClientUtils.doPost("https://way.jd.com/youhuoBeijing/test", parasMap);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("系统繁忙，请稍后再试...");
        }
        //code解析 验证通信是否异常
        JSONObject jsonObject = JSONObject.parseObject(result);
        String code1 = jsonObject.getString("code");
        if (!StringUtils.equals(code1, "10000")) {
            //接口只有免费使用10次，后面code1==10010：接口需要付费，请充值，所以只能用上面成功的假消息
            return Result.error("通信异常" + code1);
        }
        //isok解析 验证身份证号与姓名是否匹配
        Boolean isok = jsonObject.getJSONObject("result").getJSONObject("result").getBoolean("isok");
        if (!isok) {
            return Result.error("身份证号与真实姓名不匹配！");
        }
        //实名认证信息注册到登录用户
        User rUser = new User();
        rUser.setId(user.getId());
        rUser.setName(realName);
        rUser.setIdCard(idCard);
        int num = userService.realName(rUser);
        if (num != 1) {
            return Result.error("实名认证失败");
        }
        //更新session作用域的用户信息
        user.setName(realName);
        user.setIdCard(idCard);

        return Result.success();
    }

    //跳转 登录页面
    @RequestMapping("/loan/page/login")
    public String login(String ReturnUrl, Model model) {
        model.addAttribute("ReturnUrl", ReturnUrl);
        return "login";
    }

    //登录验证
    @RequestMapping("/loan/page/loginSubmit")
    @ResponseBody
    public Object loginSubmit(@RequestParam(name = "phone", required = true) String phone,
                              @RequestParam(name = "loginPassword", required = true) String loginPassword,
                              HttpServletRequest request) {
        /*
         * 登录验证两种方式:
         * 1、根据用户名和密码，查询用户，如果查询到，登录成功；否则，失败===》无法确定用户名还是密码错误
         * 2、根据用户名查询用户信息，如果查询到，匹配密码，匹配成功，登陆成功；否则，失败===》确定用户名还是密码错误
         * */
        //选择第一种验证：为了安全保密
        User user = userService.login(phone, loginPassword);
        if (!ObjectUtils.allNotNull(user)) {
            return Result.error("账户名与密码不匹配，请重新输入！");
        }
        //缓存登录身份
        request.getSession().setAttribute(Constants.LOGIN_USER, user);
        //如果用户没有实名认证，跳转到实名认证页面
        if (user.getName() == null || user.getName().equals("")) {
            return Result.error("请您实名认证后登录！");
        }
        if (user.getIdCard() == null || user.getIdCard().equals("")) {
            return Result.error("请您实名认证后登录！");
        }
        return Result.success();
    }

    /*
     * 退出登录：
     * 1、清除session中登录身份===》如果以另外账号登录，会获取之前账号留在session中的数据===》身份串位
     * 2、session失效===》session中所有数据都丢失
     * */
    @RequestMapping("/loan/logout")
    public String logout(HttpServletRequest request) {
        //1.清除session中登录身份
        // request.getSession().removeAttribute(Constants.LOGIN_USER);
        //2.session失效
        request.getSession().invalidate();
        return "redirect:/index"; //重定向 跳转首页
    }

    //个人中心：我的小金库
    @RequestMapping("/loan/page/myCenter")
    public String myCenter() {
        return "myCenter.html";
    }

    //获取本地文件 更新头像
    @PostMapping("/loan/page/uploadHeader")
    public String uploadHeader(MultipartFile file, HttpServletRequest request) throws IOException {
        //1.获取上传文件名字
        String fileName = file.getOriginalFilename();
        //2.通过上传文件名字截图后缀名
        String fileNameLast = fileName.substring(fileName.indexOf("."));
        //3.定义新的文件名字
        String newFileName = UUID.randomUUID().toString() + fileNameLast;
        //4.获取上传图片路径
        String path = ResourceUtils.getURL("classpath:").getPath() + "static/image/";
        File uploadPath = new File(path + newFileName);
        //5.如果上传目录不存在，创建目录
        if (!uploadPath.exists()) {
            uploadPath.mkdirs();
        }
        //6.上传文件
        file.transferTo(uploadPath);
        //7.更新 用户头像
        User user = (User) request.getSession().getAttribute(Constants.LOGIN_USER);
        user.setHeaderImage(newFileName);
        userService.insertHeaderImage(user);

        return "myCenter";
    }

    //查看全部充值
    @RequestMapping("/loan/page/myRecharge")
    public String myRecharge() {
        return "myRecharge.html";
    }

    //查看全部投资
    @RequestMapping("/loan/page/myInvest")
    public String myInvest() {
        return "myInvest.html";
    }

    //查看全部收益计划
    @RequestMapping("/loan/page/myIncome")
    public String myIncome() {
        return "myIncome.html";
    }
}
